package day6.singleton_demo;

/**
 * 懒汉模式
 *  双检锁/双重校验锁（DCL，即 double-checked locking）
 *  这种方式采用双锁机制，安全且在多线程情况下能保持高性能。
 */
public class LazyModeV3 {

    // 防止代码重排序出现问题
    private volatile static LazyModeV3 instance = null;

    private LazyModeV3() {}

    public static LazyModeV3 getInstance() {
        // 第一次调用这个方法时，说明我们应该实例化对象了
        if (instance == null) {
            // 只有 instance 还没有初始化时，才会走到这个分支
            // 这里没有锁保护，所以理论上可以有很多线程同时走到这个分支

            synchronized (LazyModeV3.class) {   // 通过上面的条件，
                                                // 让争抢锁的动作只在 instance
                                                // 实例化之前才可能发生
                                                // 实例化之后就不再可能
                // 加锁之后才能执行
                // 第一个抢到锁的线程，看到的 instance 是 null
                // 其他抢到锁的线程，看到的 instance 不是 null
                // 保证了 instance 只会被实例化一次
                if (instance == null) {
                    instance = new LazyModeV3();    // 只在第一次的时候执行
                    // 当重排序成 1 -> 3 -> 2 的时候可能出问题
                    // 通过 volatile 修复
                }
            }
        }
        return instance;
    }
}
